package com.xcm.service.impl;

import com.google.common.collect.Maps;
import com.xcm.config.CustomProperties;
import com.xcm.exception.ServiceException;
import com.xcm.service.FileService;
import com.xcm.util.FileUtils;
import com.xcm.util.HuaWeiCloudUtils;
import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.ApkMeta;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.rmi.ServerException;
import java.text.DecimalFormat;
import java.util.Map;

/**
 * 文件Service实现类
 */
@Service(value = "fileService")
public class FileServiceImpl implements FileService {
	@Autowired
	private CustomProperties customProperties;

	/**
	 * 保存文件(如果要返回文件的下载信息，需要传入下载文件路径和封装分析消息的Map)
	 * @param file  MultipartFile
	 * @throws IOException
	 */
	@Override
	public Map<Object, Object> saveApkFile(MultipartFile file) throws IOException {
		//返回信息Map
		Map<Object, Object> msgMap = Maps.newHashMap();
		//上传文件到华为云,返回文件保存地址
		String fileSaveURL = HuaWeiCloudUtils.uploadFile2HuaweiCloud(file, "xcips/apk/");
		if (StringUtils.isBlank(fileSaveURL)) {
			throw new ServerException("上传文件到华为云失败");
		}
		//将MultipartFile转为File
		File apkFile = FileUtils.multipartFileConvertFile(file);
		//获取apk信息,自动关闭流
		try (ApkFile apk = new ApkFile(apkFile)) {
			ApkMeta apkMeta = apk.getApkMeta();
			String apkFileMD5 = FileUtils.getApkFileMD5(apkFile);
			msgMap.put("md5", apkFileMD5);
			msgMap.put("name", apkMeta.getName());
			msgMap.put("versionCode", apkMeta.getVersionCode());
			msgMap.put("versionName", apkMeta.getVersionName());
			double size = file.getSize() / 1024 / 1024;
			DecimalFormat decimalFormat  =   new DecimalFormat("##0.0");
			msgMap.put("size", decimalFormat.format(size));
		}
		msgMap.put("file", fileSaveURL);
		msgMap.put("filename", file.getOriginalFilename());
		return msgMap;
	}

	private String buildPathName(String contextFileName) {
		return contextFileName.toString().replace("\\", "/");
	}

	/**
	 * 保存文件公共方法
	 * @param file  MultipartFile
	 * @param fileSavePath  文件保存路径
	 */
	private void saveFile(MultipartFile file, String fileSavePath) throws IOException {
		if (file == null) {
			throw new ServerException("传入文件不能为空");
		}
		//验证文件保存路径
		if (StringUtils.isBlank(fileSavePath)) {
			throw new ServerException("文件保存路径为空");
		}
		String separator = File.separator;
		//如果路径有配置系统分隔符
		if (!fileSavePath.endsWith(separator)) {
			fileSavePath = fileSavePath + separator;
		}
		// 判断文件夹是否存在
		File diskFile = new File(fileSavePath);
		if (!diskFile.exists()) {
			diskFile.mkdirs();
		}

		String originalFilename = file.getOriginalFilename();
		String fullSavePath = fileSavePath + originalFilename;
		//目标文件
		File destFile = new File(fullSavePath);
		if (destFile.exists()) {
			destFile.delete();
		}
		//保存文件
		try (BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(destFile))) {
			byte[] bytes = file.getBytes();
			stream.write(bytes);
		}
	}

	/**
	 * 下载文件
	 * @param fileName  文件名
	 * @param fileSavePath  文件保存路径
	 * @param response  HttpServletResponse
	 */
	@Override
	public void downloadLocalFile(String fileName, String fileSavePath, HttpServletResponse response) throws ServiceException, IOException {
		if (StringUtils.isBlank(fileName)) {
			throw new ServiceException("文件名为空");
		}
		if (StringUtils.isBlank(fileSavePath)) {
			throw new ServiceException("文件保存路径为空");
		}
		//buffer输入流
		BufferedInputStream bis = null;
		//输出流
		OutputStream os = null;
		//buffer输出流
		BufferedOutputStream bos = null;
		try {
			//设置reponse文件下载信息
			response.setContentType("application/octet-stream;charset=UTF-8");
			response.setCharacterEncoding("UTF-8");
			response.setHeader("Content-disposition", "attachment;filename="+ fileName);
			if (!fileSavePath.endsWith(File.separator)) {
				fileSavePath = fileSavePath + File.separator;
			}
			//获取目标文件的绝对路径
			String fullFileName = fileSavePath + fileName;
			bis = new BufferedInputStream(new FileInputStream(new File(fullFileName)));
			os = response.getOutputStream();
			bos = new BufferedOutputStream(os);

			byte[] buffer = new byte[1024];
			int len = bis.read(buffer);
			while(len != -1){
				bos.write(buffer, 0, len);
				len = bis.read(buffer);
			}
			bos.flush();
		} finally {
			if(bis != null){
				try{
					bis.close();
				}catch(IOException e){}
			}
			if(bos != null){
				try{
					bos.close();
				}catch(IOException e){}
			}
		}
	}

	/**
	 * 保存固件文件
	 *
	 * @param files
	 * @return
	 * @throws IOException
	 */
	@Override
	public Map<Object, Object> saveFirmwareFile(MultipartFile files) throws IOException {
		//固件文件保存路径
		String fileSavePath = customProperties.getFirmwareFileSavePath();
		if (StringUtils.isBlank(fileSavePath)) {
			throw new ServerException("固件文件保存路径不能为空");
		}
		//文件下载路径
		String fileDownloadPath = HuaWeiCloudUtils.uploadFile2HuaweiCloud(files, fileSavePath);
		if (StringUtils.isBlank(fileDownloadPath)) {
            throw new ServerException("上传固件文件到华为云失败");
		}
		//文件完整路径
		Map<Object, Object> msgMap = Maps.newHashMap();
		//获取文件大小
		double size = files.getSize() / 1024 / 1024;
		DecimalFormat decimalFormat  =   new DecimalFormat("##0.0");
		msgMap.put("size", decimalFormat.format(size));
        msgMap.put("file", buildPathName(fileDownloadPath));
        msgMap.put("filename", files.getOriginalFilename());
		return msgMap;
	}

}
